package com.fm.financemanage.component;

import com.alibaba.fastjson.JSONObject;
import com.fm.financemanage.exception.BusinessException;
import com.fm.financemanage.utils.TextUtil;

import io.minio.*;
import io.minio.http.Method;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import java.io.InputStream;

import java.time.ZonedDateTime;
import java.util.UUID;

@Component
@Slf4j
public class MinioComponent {


    @Value("${minio.endPoint}")
    private String endPoint ;
    @Value("${minio.accessKeyId}")
//    private String accessKeyId = "SBTVIjGWZqDYew5pePgq";
    private String accessKeyId ;
    @Value("${minio.accessKeySecret}")
//    private String accessKeySecret = "vVyjIaj3DTgeO7V10nmaZMXT0ymElpS0ow8R5yLx";
    private String accessKeySecret ;
    @Value("${minio.bucketName}")
    private String bucketName;

    private MinioClient minioClient = null;
    @Value("${minio.domain}")
//    private String domain = "http://183.250.161.122:18135";
    private String domain;


    @PostConstruct
    public void build() {
        minioClient =
                MinioClient.builder()
                        .endpoint(endPoint)
                        .credentials(this.accessKeyId, this.accessKeySecret)
                        .build();
    }


    public void createBucket() {

        MakeBucketArgs.Builder builder = MakeBucketArgs.builder()
                .bucket(bucketName).region("cn-north-1");
        try {
            minioClient.makeBucket(builder.build());
            final SetBucketPolicyArgs build = SetBucketPolicyArgs.builder().config("{\n" +
                    "    \"Version\": \"2012-10-17\",\n" +
                    "    \"Statement\": [\n" +
                    "        {\n" +
                    "            \"Effect\": \"Allow\",\n" +
                    "            \"Principal\": {\n" +
                    "                \"AWS\": [\n" +
                    "                    \"*\"\n" +
                    "                ]\n" +
                    "            },\n" +
                    "            \"Action\": [\n" +
                    "                \"s3:GetBucketLocation\",\n" +
                    "                \"s3:ListBucket\"\n" +
                    "            ],\n" +
                    "            \"Resource\": [\n" +
                    "                \"arn:aws:s3:::" + bucketName + "\"\n" +
                    "            ]\n" +
                    "        },\n" +
                    "        {\n" +
                    "            \"Effect\": \"Allow\",\n" +
                    "            \"Principal\": {\n" +
                    "                \"AWS\": [\n" +
                    "                    \"*\"\n" +
                    "                ]\n" +
                    "            },\n" +
                    "            \"Action\": [\n" +
                    "                \"s3:GetObject\"\n" +
                    "            ],\n" +
                    "            \"Resource\": [\n" +
                    "                \"arn:aws:s3:::" + bucketName + "/*\"\n" +
                    "            ]\n" +
                    "        }\n" +
                    "    ]\n" +
                    "}").bucket(bucketName).build();
            minioClient.setBucketPolicy(build);

        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException("检测bucket 不存在,创建失败");
        }
    }

    public static void main(String[] args) {

        final ZonedDateTime parse = ZonedDateTime.parse("20240407T122708Z", Time.AMZ_DATE_FORMAT);
        System.out.println(parse);
    }

    public String upload(InputStream inputStream, String filename, String folder) {
        ZonedDateTime date = ZonedDateTime.now();
        log.info("time:{}", date.format(Time.AMZ_DATE_FORMAT));
        try {
            // 检查存储桶是否已经存在
            boolean isExist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(this.bucketName).build());
            if (!isExist) {
                createBucket();
            }
            String substring = filename.substring(filename.lastIndexOf(".")).toLowerCase();
            String name = TextUtil.isEmpty(filename) ? UUID.randomUUID().toString().replaceAll("-", "") + substring : filename;
            String fullPath = folder + name;
            // 使用putObject上传一个文件到存储桶中
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketName)
                            .object(fullPath)
                            .contentType(getContentType(substring))
                            .stream(inputStream, inputStream.available(), -1)
                            .build()
            );
            return "/" + bucketName + "/" + fullPath;
        } catch (Exception e) {
            log.error("上传文件出现异常", e);
            e.printStackTrace();
        }
        return null;
    }

    public String getPresignedUploadUrl(String filePath) {

        String presignedObjectUrl = null;
        try {
            MinioClient minioClient =
                    MinioClient.builder()
                            .endpoint(endPoint)
                            .credentials(this.accessKeyId, this.accessKeySecret)
                            .build();
            // 检查存储桶是否已经存在
            boolean isExist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(this.bucketName).build());
            if (!isExist) {
                createBucket();
            }
            presignedObjectUrl = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs
                    .builder()
                    .bucket(bucketName)
                    .object(filePath)
                    .method(Method.GET)
                    .expiry(60 * 60 * 24)
                    .build());
        } catch (Exception e) {
            log.error("授权地址获取失败:", e);
        }
        return presignedObjectUrl;
    }

    public boolean removeObject(String filePath) {
        try {
            MinioClient minioClient =
                    MinioClient.builder()
                            .endpoint(endPoint)
                            .credentials(this.accessKeyId, this.accessKeySecret)
                            .build();
            // 检查存储桶是否已经存在
            boolean isExist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(this.bucketName).build());
            if (!isExist) {
                createBucket();
            }
            RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket(bucketName).object(filePath).build();
            minioClient.removeObject(removeObjectArgs);

        } catch (Exception e) {
            log.error("删除文件失败:", e);
            return false;
        }
        return true;
    }


    /**
     * Description: 判断OSS服务文件上传时文件的contentType
     *
     * @param filenameExtension 文件后缀
     * @return String
     */
    public static String getContentType(String filenameExtension) {

        if (".bmp".equalsIgnoreCase(filenameExtension)) {
            return "image/bmp";
        } else if (".gif".equalsIgnoreCase(filenameExtension)) {
            return "image/gif";
        } else if (!".jpeg".equalsIgnoreCase(filenameExtension) && !".jpg".equalsIgnoreCase(filenameExtension) && !".png".equalsIgnoreCase(filenameExtension) && !".jpe".equalsIgnoreCase(filenameExtension)) {
            if (".html".equalsIgnoreCase(filenameExtension)) {
                return "text/html";
            } else if (".txt".equalsIgnoreCase(filenameExtension)) {
                return "text/plain";
            } else if (".vsd".equalsIgnoreCase(filenameExtension)) {
                return "application/vnd.visio";
            } else if (!".pptx".equalsIgnoreCase(filenameExtension) && !".ppt".equalsIgnoreCase(filenameExtension)) {
                if (!".docx".equalsIgnoreCase(filenameExtension) && !".doc".equalsIgnoreCase(filenameExtension)) {
                    if (".xml".equalsIgnoreCase(filenameExtension)) {
                        return "text/xml";
                    } else if (".pdf".equalsIgnoreCase(filenameExtension)) {
                        return "application/pdf";
                    } else if (".svg".equalsIgnoreCase(filenameExtension)) {
                        return "image/svg+xml";
                    } else {
                        return ".zip".equalsIgnoreCase(filenameExtension) ? "application/x-zip-compressed" : "application/otcet-stream";
                    }
                } else {
                    return "application/msword";
                }
            } else {
                return "application/vnd.ms-powerpoint";
            }
        } else {
            return "image/jpg";
        }
    }
}
